package com.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * Token 工具类，用于生成、验证和管理 Token
 */
public class TokenUtils {

    @Autowired
    private static RedisUtils redisUtils;

    @Value("${jwt.secret}")
    private static String secret;

    @Value("${jwt.expiration}")
    private static Long expiration; // 单位：毫秒

    // 生成 Token

    /**
     * 生成的 JWT Token 由三部分组成，用点分隔：
     * - **Header**：包含 Token 类型和签名算法
     * - **Payload**：包含声明（如用户 ID、过期时间等）
     * - **Signature**：使用密钥生成的签名，确保 Token 不被篡改
     * @param userId
     * @return
     */
    public static String generateToken(String userId) {
        // 生成安全密钥
        SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));

        // 设置 Token 声明
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", userId);

        // 构建 JWT
        String token = Jwts.builder()
                .setClaims(claims)
                .setSubject(userId)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .signWith(key, SignatureAlgorithm.HS256)
                .compact();

        // 将 Token 存入 Redis
        redisUtils.saveToken(token, userId, expiration);

        return token;
    }

    // 验证 Token

    /**
     * 双重验证机制
     * 先验证 JWT 签名和过期时间（确保 Token 格式正确且未篡改）
     * 再验证 Redis 中是否存在该 Token（确保 Token 是有效发放的）
     * @param token
     * @return
     */
    public static boolean validateToken(String token) {
        if (token == null || token.isEmpty()) {
            return false;
        }

        try {
            // 1. 验证 JWT 签名和过期时间
            SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
            Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token);

            // 2. 验证 Redis 中是否存在该 Token
            return redisUtils.validateToken(token);
        } catch (ExpiredJwtException e) {
            // Token 过期，从 Redis 删除
            redisUtils.deleteToken(token);
            return false;
        } catch (Exception e) {
            // 其他异常（如签名无效）
            return false;
        }
    }

    // 从 Token 中获取用户ID
    public static String getUserIdFromToken(String token) {
        // 优先从 Redis 获取（效率更高）
        String userId = redisUtils.getUserIdByToken(token);
        if (userId != null) {
            return userId;
        }

        // 回退到解析 JWT（用于兼容未存储到 Redis 的情况）
        try {
            SecretKey key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            return claims.getSubject();
        } catch (ExpiredJwtException e) {
            return e.getClaims().getSubject();
        }
    }

    // 刷新 Token
    public static String refreshToken(String token) {
        if (!validateToken(token)) {
            return null;
        }

        String userId = getUserIdFromToken(token);

        // 删除旧 Token
        redisUtils.deleteToken(token);

        // 生成新 Token
        return generateToken(userId);
    }

    // 注销 Token
    public static void logout(String token) {
        if (token != null) {
            redisUtils.deleteToken(token);
        }
    }

    // 获取 Token 剩余有效期（毫秒）
    public static Long getRemainingTime(String token) {
        return redisUtils.getExpire("token:" + token, TimeUnit.MILLISECONDS);
    }


//    // 模拟 Token 存储（实际项目中建议使用 Redis）
//    private static final Map<String, String> tokenStore = new ConcurrentHashMap<>();
//
//    /**
//     * 生成 Token
//     * @param userId 用户ID
//     * @return 生成的 Token
//     */
//    public static String generateToken(String userId) {
//        String token = UUID.randomUUID().toString();
//        tokenStore.put(token, userId);
//        return token;
//    }
//
//    /**
//     * 验证 Token
//     * @param token Token 字符串
//     * @return 是否有效
//     */
//    public static boolean validateToken(String token) {
//        if (token == null || token.isEmpty()) {
//            return false;
//        }
//        return tokenStore.containsKey(token);
//    }
//
//    /**
//     * 从 Token 中获取用户ID
//     * @param token Token 字符串
//     * @return 用户ID
//     */
//    public static String getUserIdFromToken(String token) {
//        return tokenStore.get(token);
//    }
//
//    /**
//     * 清除 Token
//     * @param token Token 字符串
//     */
//    public static void removeToken(String token) {
//        tokenStore.remove(token);
//    }
}